#include "Scene.h"
#include <cassert>
#include <cmath>

using namespace LA;
using namespace CG;

/**
 * @file Scene.cpp
 * @author xingyifan
 * @date 2022-12-31 23:44
 *
 * @description: 基本创建操作
 */

Scene::Scene(CFrameWnd* pWnd, Camera* camera) : m_pWnd(pWnd), m_camera(camera)
{
	// 设置 OpenGL 绘图设备
	PIXELFORMATDESCRIPTOR pfd =
	{
		sizeof(PIXELFORMATDESCRIPTOR), // pfd 结构大小
		1,                             // 版本号
		PFD_DRAW_TO_WINDOW |           // 支持窗口绘图
			PFD_SUPPORT_OPENGL |       // 支持 OpenGL
			PFD_DOUBLEBUFFER,          // 双缓冲模式
		PFD_TYPE_RGBA,                 // RGBA 绘图模式
		24,                            // 24 位颜色深度
		0, 0, 0, 0, 0, 0,              // 忽略颜色位
		0,                             // 没有非透明度缓存
		0,                             // 忽略移位位
		0,                             // 无累计缓存
		0, 0, 0, 0,                    // 忽略累计位
		32,                            // 32 位深度缓存
		0,                             // 无模板缓存
		0,                             // 无辅助缓存
		PFD_MAIN_PLANE,                // 主层
		0,                             // 保留
		0, 0, 0                        // 忽略层，可见性和损毁掩模
	};

	CClientDC dc(pWnd);
	int pf = ChoosePixelFormat(dc.m_hDC, &pfd);
	BOOL rt = SetPixelFormat(dc.m_hDC, pf, &pfd);

	// 获得当前 RC，同时设为当前 RC
	m_hglrc = wglCreateContext(dc.m_hDC);

	// 设置当前 RC
	CPaintDC CPdc(pWnd);
	wglMakeCurrent(CPdc.m_hDC, m_hglrc);
}

Scene::~Scene()
{
	for (auto it = m_mList.begin(); it != m_mList.end(); ++it)
		if ((*it) != nullptr)
			delete (*it);
	for (auto it = m_lList.begin(); it != m_lList.end(); ++it)
		if ((*it) != nullptr)
			delete (*it);
	for (auto it = m_csList.begin(); it != m_csList.end(); ++it)
		if ((*it) != nullptr)
			delete (*it);
	for (auto it = m_dsList.begin(); it != m_dsList.end(); ++it)
		if ((*it) != nullptr)
			delete (*it);

	if (wglGetCurrentContext() != nullptr)
		wglMakeCurrent(nullptr, nullptr);

	// 销毁 RC
	if (m_hglrc != nullptr)
	{
		wglDeleteContext(m_hglrc);
		m_hglrc = nullptr;
	}
}

void Scene::LoadRC()
{
	// 设置当前 RC
	CPaintDC CPdc(m_pWnd);
	wglMakeCurrent(CPdc.m_hDC, m_hglrc);
}

void Scene::RemoveRC()
{
	// 取消当前 RC
	wglMakeCurrent(nullptr, nullptr);
}

/**
 * @file Scene.cpp
 * @author xingyifan
 * @date 2023-01-01 16:30
 *
 * @description: 网格创建和销毁
 */

int Scene::CreateMesh()
{
	Mesh* mesh = new Mesh;
	m_mList.push_back(mesh);

	return m_mList.size() - 1;
}

bool Scene::DeleteMesh(int i)
{
	if (i < m_mList.size() && m_mList[i] != nullptr)
	{
		delete m_mList[i];
		m_mList[i] = nullptr;
		m_mList.erase(m_mList.begin() + i);
		return true;
	}
	return false;
}

/**
 * @file Scene.cpp
 * @author xingyifan
 * @date 2023-01-01 16:18
 *
 * @description: 注册网格信息
 */

void Scene::RegisterMesh(int i)
{
	Mesh* mesh = m_mList[i];

	// 计算网格包围盒
	mesh->GetBox();

	// 如果没有法向，就插值计算顶点法向
	if (!mesh->HasVertexNormal())
		for (int i = 0; i < mesh->VertexNum(); i++)
			mesh->m_nList.push_back(mesh->Gouraud(mesh->m_vList[i]));
}

/**
 * @file Scene.cpp
 * @author xingyifan
 * @date 2023-01-01 14:16
 *
 * @description: 设置光照
 */

int Scene::CreateLighting(coord4f pos, double L[][3], double* reduce)
{
	Lighting* light = new Lighting;
	m_lList.push_back(light);

	// 设置光源位置
	if (pos.w == 1)
		light->SetPoint(pos.x, pos.y, pos.z);
	else
		light->SetParallel(pos.x, pos.y, pos.z);

	// 设置颜色和衰减因子
	light->SetLighting(L);
	light->SetReduce(reduce[0], reduce[1], reduce[2]);

	return m_lList.size() - 1;
}

bool Scene::DeleteLighting(int i)
{
	if (i < m_lList.size() && m_lList[i] != nullptr)
	{
		delete m_lList[i];
		m_lList[i] = nullptr;
		m_lList.erase(m_lList.begin() + i);
		return true;
	}
	return false;
}

/**
 * @file Scene.cpp
 * @author xingyifan
 * @date 2023-01-11 11:49
 *
 * @description: 创建交互
 */

int Scene::CreateClick(ClickType type)
{
	m_csList.push_back(ClickScene::Create(type));
	return m_csList.size() - 1;
}

int Scene::CreateDraw(DrawType type)
{
	m_dsList.push_back(DrawScene::Create(type));
	return m_dsList.size() - 1;
}

bool Scene::DeleteClick(int i)
{
	if (i < m_csList.size() && m_csList[i] != nullptr)
	{
		delete m_csList[i];
		m_csList[i] = nullptr;
		m_csList.erase(m_csList.begin() + i);
		return true;
	}
	return false;
}

bool Scene::DeleteDraw(int i)
{
	if (i < m_dsList.size() && m_dsList[i] != nullptr)
	{
		delete m_dsList[i];
		m_dsList[i] = nullptr;
		m_dsList.erase(m_dsList.begin() + i);
		return true;
	}
	return false;
}

/**
 * @file Scene.cpp
 * @author xingyifan
 * @date 2023-01-11 00:27
 *
 * @description: 计算光照，同时绘制场景
 */

void Scene::Draw()
{
	// 开启深度测试，清除缓冲
	glEnable(GL_DEPTH_TEST);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	// 调用列表中的绘制函数
	for (auto it = m_dsList.begin(); it != m_dsList.end(); it++)
		(*it)->Draw(this);

	// 刷新缓冲
	glFlush();

	// 与 DC 交换缓冲，这是图像显示的最后一步
	CPaintDC dc(m_pWnd);
	SwapBuffers(dc.m_hDC);
}

/**
 * @file Scene.cpp
 * @author xingyifan
 * @date 2023-01-11 11:37
 *
 * @description: 点击操作
 */

void Scene::Click()
{
	// 调用列表中的点击函数
	for (auto it = m_csList.begin(); it != m_csList.end(); it++)
		(*it)->React(this);
}